home *** CD-ROM | disk | FTP | other *** search
/ ETO Development Tools 1 / ETO Development Tools 1.iso / Tools - Objects / MacApp / MacApp 2.0 CD Release / MacApp 2.0 (Many Libraries) / Libraries / UTEView.TTEView.p < prev    next >
Encoding:
Text File  |  1990-03-27  |  50.0 KB  |  1,852 lines  |  [TEXT/MPS ]

  1. {$P}
  2. {[a-,body+,h-,o=100,r+,rec+,t=4,u+,#+,j=20/57/1$,n-]}
  3. { UTEView.TTEView.p }
  4. { Copyright © 1984-1990 Apple Computer Inc.  All rights reserved. }
  5.  
  6. {--------------------------------------------------------------------------------------------------}
  7. {$S TEOpen}
  8.  
  9. PROCEDURE TTEView.ITEView(itsDocument: TDocument;
  10.                           itsSuperView: TView;
  11.                           itsLocation, itsSize: VPoint;
  12.                           itsHDeterminer, itsVDeterminer: SizeDeterminer;
  13.                           itsInset: Rect;
  14.                           itsTextStyle: TextStyle;
  15.                           itsJustification: INTEGER;
  16.                           itsStyleType, itsAutoWrap: BOOLEAN);
  17.  
  18.     BEGIN
  19.     {$IFC qDebug}
  20.     IF NOT gUTEViewInitialized THEN
  21.         BEGIN
  22.         ProgramBreak('InitUTEView must be called before creating a TE View.');
  23.         Failure(noErr, 0);
  24.         END;
  25.     {$ENDC}
  26.  
  27.     {$IFC qDebug}
  28.     pTEIntenseDebugging := FALSE;
  29.     {$ENDC}
  30.  
  31.     fHTE := NIL;
  32.     fText := NIL;
  33.     fSavedTEHandle := NIL;
  34.     fInset := itsInset;
  35.     fKeyCmdNumber := cTyping;
  36.     fMaxChars := kUnlimited;
  37.     fLastHeight := 0;
  38.     fLastWidth := 0;
  39.     fTypingCommand := NIL;
  40.     fTextStyle := itsTextStyle;
  41.     fJustification := itsJustification;
  42.  
  43.     fAcceptsChanges := TRUE;                            { Stuff to FALSE if you don't want to allow
  44.                                                          Cut, Paste, or Typing }
  45.     {!!! put these in the template after 2.0 !!!}
  46.     fControlChars := [chLeft, chRight, chUp, chDown, chBackspace, chReturn];
  47.     fMinAhead := kMinAhead;
  48.  
  49.     fStyleType := (qNeedsStyleTextEdit | gConfiguration.hasStyleTextedit) & itsStyleType;
  50.     fAutoWrap := itsAutoWrap;
  51.     fFreeText := FALSE;
  52.     fSpecsChanged := FALSE;
  53.  
  54.     fLastPageBreak := 0;
  55.     fLastLine := 0;
  56.  
  57.     IView(itsDocument, itsSuperView, itsLocation, itsSize, itsHDeterminer, itsVDeterminer);
  58.  
  59.     MakeTERecord;
  60.  
  61.     SetClikLoop(@ClickLoopForTTEView, fHTE);                { fHTE^^.clikLoop := @ClickLoopForTTEView; }
  62.     { ??? Things don't work well if fText is non-NIL.  Is this the way to solve it? }
  63.     fText := fHTE^^.hText;
  64.  
  65.     SetIdleFreq(0);                                     { Idle ASAP }
  66.     END;
  67.  
  68. {--------------------------------------------------------------------------------------------------}
  69. {$S TEOpen}
  70.  
  71. PROCEDURE TTEView.IRes(itsDocument: TDocument;
  72.                        itsSuperView: TView;
  73.                        VAR itsParams: Ptr); OVERRIDE;
  74.  
  75.     VAR
  76.         aTextStyle:         TextStyle;
  77.  
  78.     BEGIN
  79.     {$IFC qDebug}
  80.     IF NOT gUTEViewInitialized THEN
  81.         BEGIN
  82.         ProgramBreak('InitUTEView must be called before creating a TE View.');
  83.         Failure(noErr, 0);
  84.         END;
  85.     {$ENDC}
  86.  
  87.     {$IFC qDebug}
  88.     pTEIntenseDebugging := FALSE;
  89.     {$ENDC}
  90.  
  91.     fHTE := NIL;                                        { In case of emergency. }
  92.     fText := NIL;
  93.     fSavedTEHandle := NIL;
  94.     fLastPageBreak := 0;
  95.     fLastLine := 0;
  96.  
  97.     {!!! put these in the template after 2.0 !!!}
  98.     fControlChars := [chLeft, chRight, chUp, chDown, chBackspace, chReturn];
  99.     fMinAhead := kMinAhead;
  100.  
  101.     INHERITED IRes(itsDocument, itsSuperView, itsParams);
  102.  
  103.     WITH TEViewTemplatePtr(itsParams)^ DO
  104.         BEGIN
  105.         fTypingCommand := NIL;
  106.         fLastHeight := 0;
  107.         fLastWidth := 0;
  108.         fSpecsChanged := FALSE;
  109.  
  110.         fInset := itsInset;
  111.         fKeyCmdNumber := itsKeyCmdNumber;
  112.         fMaxChars := itsMaxChars;
  113.         SetTextStyle(aTextStyle, GetFontNum(itsFontName), itsTextFace, itsTextSize, itsTextColor);
  114.         fTextStyle := aTextStyle;
  115.         fJustification := itsJustification;
  116.         fAcceptsChanges := itsAcceptsChanges;
  117.         fStyleType := (qNeedsStyleTextEdit | gConfiguration.hasStyleTextedit) & itsStyleType;
  118.         fAutoWrap := itsAutoWrap;
  119.         fFreeText := itsFreesText;
  120.  
  121.         MakeTERecord;
  122.  
  123.         SetClikLoop(@ClickLoopForTTEView, fHTE);        { fHTE^^.clikLoop := @ClickLoopForTTEView; }
  124.         fText := fHTE^^.hText;
  125.  
  126.         SetIdleFreq(0);                                 { Idle ASAP }
  127.         END;
  128.  
  129.     OffsetPtrWStr(itsParams, SIZEOF(TEViewTemplate));
  130.     END;
  131.  
  132. {--------------------------------------------------------------------------------------------------}
  133. {$S MAWriteRes}
  134.  
  135. PROCEDURE TTEView.WRes(theResource: ViewRsrcHndl;
  136.                        VAR itsParams: Ptr); OVERRIDE;
  137.  
  138.     VAR
  139.         theFont:            Str255;
  140.         ttPtr:                TEViewTemplatePtr;
  141.  
  142.     BEGIN
  143.     INHERITED WRes(theResource, itsParams);
  144.  
  145.     GetFontName(fTextStyle.tsFont, theFont);
  146.  
  147.     ttPtr := TEViewTemplatePtr(ExpandPtrWStr(theResource, itsParams, SIZEOF(TEViewTemplate),
  148.                                              LENGTH(theFont)));
  149.  
  150.     WITH ttPtr^ DO
  151.         BEGIN
  152.         itsStyleType := fStyleType;
  153.         itsAutoWrap := fAutoWrap;
  154.         itsAcceptsChanges := fAcceptsChanges;
  155.         itsFreesText := fFreeText;
  156.         itsKeyCmdNumber := fKeyCmdNumber;
  157.         itsMaxChars := fMaxChars;
  158.         itsInset := fInset;
  159.         itsJustification := fJustification;
  160.         WITH fTextStyle DO
  161.             BEGIN
  162.             itsTextFace := tsFace;
  163.             itsTextSize := tsSize;
  164.             itsTextColor := tsColor;
  165.             END;
  166.         { itsFontName := theFont; }
  167.         CopyStr255(theFont, PRStr(itsFontName));
  168.         END;
  169.     END;
  170.  
  171. {--------------------------------------------------------------------------------------------------}
  172. {$S MAWriteRes}
  173.  
  174. PROCEDURE TTEView.WriteRes(theResource: ViewRsrcHndl;
  175.                            VAR itsParams: Ptr); OVERRIDE;
  176.  
  177.     BEGIN
  178.     gWResSignature := 'tevw'; gWResType := 'TTEView';
  179.     WRes(theResource, itsParams);
  180.     END;
  181.  
  182. {--------------------------------------------------------------------------------------------------}
  183. {$S TEClose}
  184.  
  185. PROCEDURE TTEView.Free; OVERRIDE;
  186.  
  187.     BEGIN
  188.     IF fHTE <> NIL THEN
  189.         BEGIN
  190.         IF fSavedTEHandle <> NIL THEN
  191.             WITH fHTE^^ DO
  192.                 BEGIN                                    { Worry about fText separately. Put back }
  193.                 hText := fSavedTEHandle;                { …the handle which TE allocated }
  194.                 {$Push} {$H-}
  195.                 teLength :=                             { This is here because it only makes }
  196.                   GetHandleSize(hText);
  197.                 IF fFreeText THEN                        { …sense if fSavedTEHandle is not NIL. }
  198.                     fText := DisposeIfHandle(fText);
  199.                 fText := NIL;                            { Always drop my reference }
  200.                 {$Pop}
  201.                 END;
  202.         TEDispose(fHTE);
  203.         fHTE := NIL;
  204.  
  205.         fSavedTEHandle := NIL;
  206.         END;
  207.  
  208.     INHERITED Free;
  209.     END;
  210.  
  211. {--------------------------------------------------------------------------------------------------}
  212. {$S TENonRes}
  213.  
  214. FUNCTION TTEView.ClikLoop: BOOLEAN;
  215.  
  216.     VAR
  217.         msePt:                Point;
  218.         viewPt:             VPoint;
  219.         visRect:            Rect;
  220.         delta:                VPoint;
  221.         vhs:                VHSelect;
  222.         lead:                INTEGER;
  223.         trail:                INTEGER;
  224.         scroller:            TScroller;
  225.  
  226.     BEGIN
  227.     IF StillDown THEN
  228.         BEGIN
  229.         scroller := GetScroller(FALSE);
  230.         IF (scroller <> NIL) & scroller.Focus THEN
  231.             BEGIN
  232.             GetMouse(msePt);
  233.             scroller.QDToViewPt(msePt, viewPt);
  234.             scroller.AutoScroll(viewPt, delta);    { find how much should scroll }
  235.             IF Focus THEN
  236.                 BEGIN
  237.                 GetVisibleRect(visRect);
  238.     
  239.                 FOR vhs := v TO h DO
  240.                     BEGIN
  241.                     lead := fLocation.vh[vhs] - visRect.topLeft.vh[vhs];
  242.                     trail := fLocation.vh[vhs] + fSize.vh[vhs] - visRect.botRight.vh[vhs];
  243.     
  244.                     IF delta.vh[vhs] < 0 THEN
  245.                         delta.vh[vhs] := Min(MAX(delta.vh[vhs], lead), 0)
  246.                     ELSE
  247.                         delta.vh[vhs] := MAX(Min(delta.vh[vhs], trail), 0);
  248.                     END;
  249.                 { The intent of the above is not to do autoscrolling that would scroll
  250.                   beyond the subview boundary in any direction }
  251.     
  252.                 IF (delta.v <> 0) | (delta.h <> 0) THEN
  253.                     BEGIN
  254.                     scroller.ScrollBy(delta.h, delta.v, kRedraw);
  255.                     Update;    { make sure the scrolling was visible }
  256.                     END;
  257.                 END;
  258.             END;
  259.         
  260.         {!!! need an IsCursorRgnValid method }
  261.         IF EmptyRgn(gCursorRgn) & gApplication.TrackCursor THEN;
  262.  
  263.         { Focus may have changed, which could change lots of things, thus
  264.         requiring us, tiresomely, to take some or all of the following
  265.         restorative precautions b/c clikloop expects us to be clipped to the
  266.         destrect. }
  267.         IF Focus THEN
  268.             ClipFurtherTo(fHTE^^.destRect, 0, 0);
  269.         END;
  270.     ClikLoop := TRUE;                                    { Still consider the mouse to be down }
  271.     END;
  272.  
  273. {--------------------------------------------------------------------------------------------------}
  274. {$S TENonRes}
  275.  
  276. PROCEDURE TTEView.AutoScrolling(doScrolling: BOOLEAN);
  277.  
  278.     BEGIN
  279.     IF qNeedsROM128K | gConfiguration.hasROM128K THEN
  280.         IF fHTE <> NIL THEN
  281.             TEAutoView(doScrolling, fHTE);
  282.     END;
  283.  
  284. {--------------------------------------------------------------------------------------------------}
  285. {$S TENonRes}
  286.  
  287. PROCEDURE TTEView.BeInPort(itsPort: GrafPtr); OVERRIDE;
  288.  
  289.     BEGIN
  290.  
  291.     IF fHTE <> NIL THEN
  292.         BEGIN
  293.         WITH fHTE^^ DO
  294.             IF itsPort = NIL THEN
  295.                 inPort := gWorkPort
  296.             ELSE
  297.                 inPort := itsPort;
  298.  
  299.         IF itsPort = NIL THEN
  300.             BEGIN
  301.             DoneTyping;
  302.             fSpecsChanged := TRUE;
  303.             END;
  304.         END;
  305.  
  306.     INHERITED BeInPort(itsPort);
  307.     END;
  308.  
  309. {--------------------------------------------------------------------------------------------------}
  310. {$S TENonRes}
  311.  
  312. PROCEDURE TTEView.BeInScroller(itsScroller: TScroller); OVERRIDE;
  313.  
  314.     VAR
  315.         vertScrollUnit:     INTEGER;
  316.  
  317.     BEGIN
  318.     IF (fHTE <> NIL) & (itsScroller <> NIL) THEN
  319.         BEGIN
  320.         IF fHTE^^.lineHeight > 0 THEN                    { This works for both old & new TextEdit }
  321.             vertScrollUnit := fHTE^^.lineHeight
  322.         ELSE IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN { Ask for system default
  323.                     size }
  324.             vertScrollUnit := GetDefFontSize
  325.         ELSE
  326.             vertScrollUnit := kStdScrollUnit;
  327.  
  328.         itsScroller.SetScrollParameters(kStdScrollUnit, vertScrollUnit, FALSE, TRUE);
  329.         END;
  330.  
  331.     INHERITED BeInScroller(itsScroller);
  332.     END;
  333.  
  334. {--------------------------------------------------------------------------------------------------}
  335. {$S TENonRes}
  336.  
  337. PROCEDURE TTEView.CalcMinSize(VAR minSize: VPoint); OVERRIDE;
  338.  
  339.     BEGIN
  340.  { Note that we omit the margins here, so that if TView.ComputeExtent rounds up to a
  341.    page multiple, the margins will get tacked on after.  Also, insure we don't run off
  342.    the end of the coordinate system if there are many lines of text. }
  343.  
  344.     SetVPt(minSize, fSize.h - fInset.left - fInset.right, Min(kMaxCoord, CalcRealHeight));
  345.  
  346.     IF (fSizeDeterminer[h] = sizeVariable) & NOT fStyleType & NOT fAutoWrap THEN
  347.         SetVPt(minSize, fLastWidth, minSize.v);
  348.  
  349.     END;
  350.  
  351. {--------------------------------------------------------------------------------------------------}
  352. {$S TERes}
  353.  
  354. FUNCTION TTEView.CalcRealHeight: LONGINT;
  355.  
  356.     VAR
  357.         lastIsCR:            BOOLEAN;
  358.         theMode:            INTEGER;
  359.         theHeight:            LONGINT;
  360.         theStyle:            TextStyle;
  361.         theFontInfo:        FontInfo;
  362.  
  363.     BEGIN
  364.     {$Push} {$R-}
  365.     WITH fHTE^^ DO
  366.         lastIsCR := (teLength <= 0) | (CharsHandle(hText)^^[PRED(teLength)] = chReturn);
  367.     {$Pop}
  368.  
  369.     IF fStyleType = kWithStyle THEN
  370.         BEGIN
  371.         theHeight := 0;
  372.         IF fHTE^^.nLines > 0 THEN
  373.             theHeight := TEGetHeight(0, MAXINT, fHTE);
  374.  
  375.         IF lastIsCR THEN                                { then can't use TEGetHeight so we }
  376.             BEGIN                                        { …have to figure it out ourselves. }
  377.             theMode := doAll;
  378.             lastIsCR := ContinuousStyle(MAXINT, MAXINT, theMode, theStyle);
  379.  
  380.             GetTextStyleFontInfo(theStyle, theFontInfo);
  381.  
  382.             WITH theFontInfo DO
  383.                 theHeight := theHeight + ascent + descent + leading;
  384.             END;
  385.         END
  386.     ELSE
  387.         BEGIN
  388.         theHeight := fHTE^^.nLines + ORD(lastIsCR);
  389.         theHeight := theHeight * fHTE^^.lineHeight;
  390.         END;
  391.  
  392.     CalcRealHeight := theHeight;
  393.     {$IFC qDebug}
  394.     IF gIntenseDebugging THEN
  395.         WRITELN('CalcRealHeight=', theHeight: 0);
  396.     {$ENDC}
  397.     END;
  398.  
  399. {--------------------------------------------------------------------------------------------------}
  400. {$S TERes}
  401.  
  402. FUNCTION TTEView.CalcRealWidth: LONGINT;
  403.  
  404.     VAR
  405.         index: INTEGER;
  406.         wasLocked: BOOLEAN;
  407.         fromChar: INTEGER;
  408.         toChar: INTEGER;
  409.         aWidth: INTEGER;
  410.         theStyle: TextStyle;
  411.  
  412.     BEGIN
  413.     { !!! it would be nice to compute this for styled TE but TEGetPoint only returns the bottom
  414.     left of the character box so it can't be used to find the width including last character
  415.     in a line.    And since some characters can change width based on context we can't just
  416.     measure the last character and add it in.  Maybe we can makeup an formula based on
  417.     style runs or something eventually. }
  418.     IF NOT fStyleType THEN
  419.         BEGIN
  420.         IF Focus THEN
  421.             BEGIN
  422.             theStyle := fTextStyle;
  423.             SetPortTextStyle(theStyle);
  424.         
  425.             aWidth := 0;
  426.             fromChar := fHTE^^.lineStarts[0];
  427.     
  428.             wasLocked := IsHandleLocked(fHTE^^.hText);
  429.             HLock(Handle(fHTE^^.hText));                        {??? Better to LockHandleHigh? }
  430.     
  431.             FOR index := 1 TO fHTE^^.nLines DO
  432.                 BEGIN
  433.                 toChar := fHTE^^.lineStarts[index] - 1;
  434.                 aWidth := Max(aWidth, TextWidth(fHTE^^.hText^, fromChar, (toChar - fromChar) + 1));
  435.                 fromChar := toChar + 1;
  436.                 END;
  437.     
  438.             IF NOT wasLocked THEN
  439.                 HUnlock(Handle(fHTE^^.hText));
  440.     
  441.             CalcRealWidth := aWidth;
  442.             END
  443.         END
  444.     ELSE IF qDebug THEN
  445.         ProgramBreak('IN TTEView.CalcRealWidth: called for a styled TE Record');
  446.     END;
  447.  
  448. {--------------------------------------------------------------------------------------------------}
  449. {$S TENonRes}
  450.  
  451. PROCEDURE TTEView.ChangeWrap(newAutoWrap, redraw: BOOLEAN);
  452.  
  453.     BEGIN
  454.     fAutoWrap := newAutoWrap;
  455.     WITH fHTE^^ DO
  456.         IF newAutoWrap THEN
  457.             crOnly := 0
  458.         ELSE
  459.             crOnly := - 1;
  460.     IF redraw THEN
  461.         BEGIN
  462.         RecalcText;
  463.         SynchView(kRedraw);
  464.         END;
  465.     END;
  466.  
  467. {--------------------------------------------------------------------------------------------------}
  468. {$S TENonRes}
  469.  
  470. PROCEDURE TTEView.ComputeSize(VAR newSize: VPoint); OVERRIDE;
  471.  
  472.     FUNCTION NeedAdjust(vhs: VHSelect): BOOLEAN;
  473.  
  474.         BEGIN
  475.         NeedAdjust := NOT (fSizeDeterminer[vhs] IN [sizeFixed, sizeSuperView, sizeRelSuperView]);
  476.         END;
  477.  
  478.     BEGIN                                                { TTEView.ComputeSize }
  479.     INHERITED ComputeSize(newSize);
  480.  
  481.     IF NeedAdjust(h) THEN                                { If necessary, tack on the margins }
  482.         newSize.h := Min(kMaxCoord, ORD4(newSize.h) + fInset.left + fInset.right);
  483.     IF NeedAdjust(v) THEN
  484.         newSize.v := Min(kMaxCoord, ORD4(newSize.v) + fInset.top + fInset.bottom);
  485.     END;
  486.  
  487. {--------------------------------------------------------------------------------------------------}
  488. {$S TERes}
  489.  
  490. PROCEDURE TTEView.CalcSelLoc(VAR selectionRect: Rect);
  491.  
  492.     CONST
  493.         kSlopToAllow        = 36;
  494.  
  495.     VAR
  496.         handleToText:        CharsHandle;
  497.         startOfSelection:    INTEGER;
  498.         endOfSelection:     INTEGER;
  499.         startOfCurrentLine: INTEGER;
  500.         startOfNextLine:    INTEGER;
  501.         charCount:            INTEGER;
  502.         selLine:            INTEGER;
  503.         upToSelWidth:        INTEGER;
  504.         restWidth:            INTEGER;
  505.         lineHeight:         INTEGER;
  506.         fontAscent:         INTEGER;
  507.         theStyle:            TextStyle;
  508.         keyDirection:        SignedByte;
  509.         selectionIsTheLastReturn: BOOLEAN;
  510.         theMode:            INTEGER;
  511.         theFontInfo:        FontInfo;
  512.         just:                INTEGER;
  513.  
  514.     BEGIN
  515.     WITH fHTE^^ DO
  516.         BEGIN
  517.         charCount := teLength;
  518.         startOfSelection := selStart;
  519.         endOfSelection := selEnd;
  520.         handleToText := CharsHandle(hText);
  521.  
  522.         IF (selEnd - selStart = 0) & (fIdleFreq = kMaxIdleTime) THEN
  523.             SetIdleFreq(0);                             { Idle ASAP }
  524.         END;
  525.  
  526.     {$Push} {$R-}
  527.     selectionIsTheLastReturn := (startOfSelection = charCount) & (charCount > 0) &
  528.                                 (handleToText^^[charCount - 1] = chReturn);
  529.     {$Pop}
  530.  
  531.     IF qNeedsStyleTextEdit | gConfiguration.hasStyleTextedit THEN
  532.         BEGIN
  533.         selectionRect.topLeft := TEGetPoint(startOfSelection, fHTE);
  534.  
  535.         { TEGetPoint returns the baseline point.  Correct for the lineheight }
  536.         TEGetStyle(startOfSelection, theStyle, lineHeight, fontAscent, fHTE);
  537.         selectionRect.top := selectionRect.top - lineHeight;
  538.  
  539.         selectionRect.botRight := TEGetPoint(endOfSelection, fHTE); { Darn! wish we could know where
  540.                                                                      the point to the bottom right
  541.                                                                      of an offset is!!! This way we
  542.                                                                      can't ever return the "real"
  543.                                                                      rectangle that encloses the
  544.                                                                      selection. }
  545.  
  546.         IF charCount = 0 THEN                            { In System 6 TE TEGetPoint returns bogus
  547.                                                          numbers when the character count is 0. }
  548.             WITH selectionRect DO
  549.                 BEGIN
  550.                 top := 0;
  551.                 bottom := lineHeight;
  552.                 END;
  553.  
  554.         IF selectionIsTheLastReturn THEN
  555.             BEGIN
  556.             theMode := doAll;
  557.  
  558.            { Get the style so we know how tall to make the selection when its just the last return }
  559.             IF ContinuousStyle(MAXINT, MAXINT, theMode, theStyle) THEN; { discard result }
  560.  
  561.             GetTextStyleFontInfo(theStyle, theFontInfo);
  562.  
  563.             selectionRect.top := selectionRect.bottom;
  564.             WITH theFontInfo DO
  565.                 selectionRect.bottom := selectionRect.top + ascent + descent + leading;
  566.             END
  567.         ELSE
  568.             BEGIN
  569. { Correct errors by CalcSelLoc.  If there is no selection then the "selection" consists of
  570. the bits enclosed by the insertion bar. }
  571.             WITH fHTE^^ DO
  572.                 BEGIN
  573.                 IF (selEnd - selStart = 0) THEN
  574.                     selectionRect.left := selectionRect.right - 1;
  575.                 END;
  576.  
  577.             END
  578.         END
  579.     ELSE                                                { Non-styled, ugh! do all the measuring
  580.                                                          ourselves }
  581.         BEGIN
  582.  
  583.         WITH fHTE^^ DO                                    { for lineStarts and nLines }
  584.             BEGIN
  585.             selLine := 1;
  586.             WHILE (selLine < nLines) & (startOfSelection >= lineStarts[selLine]) DO
  587.                 selLine := selLine + 1;
  588.             selLine := selLine - 1;
  589.  
  590.             IF selectionIsTheLastReturn | (fJustification <> teJustLeft) & (startOfSelection =
  591.                lineStarts[SUCC(selLine)]) THEN
  592.                 selLine := SUCC(selLine);
  593.  
  594.             selectionRect.top := (lineHeight * selLine) + fInset.top;
  595.             startOfCurrentLine := lineStarts[selLine];
  596.             IF selLine < nLines THEN
  597.                 startOfNextLine := lineStarts[SUCC(selLine)]
  598.             ELSE
  599.                 startOfNextLine := charCount;
  600.             END;
  601.  
  602.         { We could move the handle high first, but this routine is called frequently and
  603.         fragmentation shouldn't be a problem for the TextWidth call--the worst that will
  604.         happen is the Font Manager will have to substitute a font & we'll be off slightly.}
  605.         { ??? The following Text calls may be unnecessary, since this may only get done
  606.         after TextEdit has run and set the font already.  This appears not to be the case
  607.         for the Select All command, however, and is not true in general. }
  608.         TextFont(fHTE^^.txFont);
  609.         TextFace(fHTE^^.txFace);
  610.         TextSize(fHTE^^.txSize);
  611.         HLock(Handle(handleToText));
  612.  
  613.         { Figure out where on the line the selection is. If the Script Manager is
  614.         installed, use it. Otherwise, try and figure it out ourselves. }
  615.         IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN
  616.             BEGIN
  617.             { Unfortunately, we must get this every time, as the user can change script
  618.             directions at a moment's notice. }
  619.             IF startOfSelection = endOfSelection THEN
  620.                 keyDirection := GetScript(GetEnvirons(smKeyScript), smScriptRight)
  621.             ELSE
  622.                 keyDirection := smHilite;
  623.  
  624.             upToSelWidth := Char2Pixel(Ptr(ORD(handleToText^) + startOfCurrentLine),
  625.                                        startOfNextLine - startOfCurrentLine, 0, startOfSelection -
  626.                                        startOfCurrentLine, keyDirection);
  627.             restWidth := TextWidth(QDPtr(handleToText^), startOfCurrentLine, startOfNextLine -
  628.                                    startOfCurrentLine) - upToSelWidth;
  629.             END
  630.         ELSE
  631.             BEGIN
  632.             upToSelWidth := TextWidth(QDPtr(handleToText^), startOfCurrentLine, startOfSelection -
  633.                                       startOfCurrentLine);
  634.             restWidth := TextWidth(QDPtr(handleToText^), startOfSelection, startOfNextLine -
  635.                                    startOfSelection);
  636.             END;
  637.  
  638.         HUnlock(Handle(handleToText));
  639.  
  640.         just := fJustification;
  641.  
  642.         {!!!### come back and fix this or just stop supporting systems without style TE }
  643.         CASE just OF
  644.             teJustLeft:
  645.                 selectionRect.left := fInset.left + upToSelWidth;
  646.             teJustRight:
  647.                 selectionRect.left := fSize.h - fInset.right - restWidth;
  648.             { Following looks somewhat baroque, but avoids integer overflow }
  649.             teJustCenter:
  650.                 selectionRect.left := fSize.h DIV 2 - restWidth DIV 2 + upToSelWidth DIV 2;
  651.         END;
  652.  
  653.         WITH selectionRect DO
  654.             BEGIN
  655.             left := MAX(left - 2, 0);
  656.             IF left <= kSlopToAllow THEN
  657.                 left := 0;                                { show start of line if close; gets around }
  658.             { …potential annoyance assoc w/typeahead }
  659.             right := Min(left + 8, fSize.h);
  660.             bottom := Min(top + fHTE^^.lineHeight, fSize.v);
  661.             END;
  662.         END;
  663.     END;
  664.  
  665. {--------------------------------------------------------------------------------------------------}
  666. {$S TERes}
  667.  
  668. FUNCTION TTEView.ContinuousStyle(firstChar, lastChar: INTEGER;
  669.                                  VAR mode: INTEGER;
  670.                                  VAR aStyle: TextStyle): BOOLEAN;
  671.  
  672.     VAR
  673.         oldSelStart, oldSelEnd: INTEGER;
  674.  
  675.     BEGIN
  676.     WITH fHTE^^ DO
  677.         BEGIN
  678.         oldSelStart := selStart;
  679.         oldSelEnd := selEnd;
  680.         END;
  681.     SetSelect(firstChar, lastChar, fHTE);                { Use SetSelect so this is invisible }
  682.     ContinuousStyle := TEContinuousStyle(mode, aStyle, fHTE);
  683.     SetSelect(oldSelStart, oldSelEnd, fHTE);
  684.     END;
  685.  
  686. {--------------------------------------------------------------------------------------------------}
  687. {$S TERes}
  688.  
  689. FUNCTION TTEView.ContainsClipType(aType: ResType): BOOLEAN; OVERRIDE;
  690.  
  691.     BEGIN
  692.     ContainsClipType := (aType = 'TEXT');
  693.     END;
  694.  
  695. {--------------------------------------------------------------------------------------------------}
  696. { Put in resident segment since this gets called while typing }
  697. {$S TERes}
  698.  
  699. FUNCTION TTEView.DoBreakFollowing(vhs: VHSelect;
  700.                                   prevBreak: VCoordinate;
  701.                                   VAR automatic: BOOLEAN): VCoordinate; OVERRIDE;
  702.  
  703.     VAR
  704.         orthoVhs:            VHSelect;
  705.         possibleLoc:        INTEGER;
  706.         theStyles:            TEStyleHandle;
  707.         lhTab:                LHHandle;
  708.         height, lineHeight: INTEGER;
  709.         lineNo:             INTEGER;
  710.  
  711.     BEGIN
  712.     orthoVhs := gOrthogonal[vhs];
  713.     automatic := TRUE;
  714.  
  715.     possibleLoc := Min(kMaxCoord, ORD4(prevBreak) + fPrintHandler.fViewPerPage.vh[orthoVhs]);
  716.  
  717.  { We want to get rid of the on-screen margin represented by fMargin when printing, so
  718.    adjust things so that the portion of the view occupied by the screen margin doesn't
  719.    get printed. }
  720.     IF prevBreak = 0 THEN
  721.         possibleLoc := possibleLoc + fInset.topLeft.vh[orthoVhs];
  722.  
  723.     IF (fStyleType = kWithStyle) & (vhs = h) THEN
  724.         BEGIN
  725.         IF (fLastPageBreak = prevBreak) THEN
  726.             BEGIN
  727.             height := fLastPageBreak;
  728.             lineNo := fLastLine;
  729.             END
  730.         ELSE
  731.             BEGIN
  732.             height := fInset.topLeft.vh[orthoVhs];
  733.             lineNo := 0;
  734.             END;
  735.  
  736.         theStyles := GetStylHandle(fHTE);
  737.         lhTab := theStyles^^.lhTab;
  738.         WHILE lineNo < fHTE^^.nLines DO
  739.             BEGIN
  740.             lineHeight := lhTab^^[lineNo].lhHeight;
  741.             IF height + lineHeight <= possibleLoc THEN
  742.                 height := height + lineHeight
  743.             ELSE
  744.                 LEAVE;
  745.             lineNo := lineNo + 1;
  746.             END;
  747.         IF lineNo >= fHTE^^.nLines THEN
  748.             possibleLoc := MAX(possibleLoc, height)
  749.         ELSE
  750.             possibleLoc := height;
  751.         fLastPageBreak := possibleLoc;
  752.         fLastLine := lineNo;
  753.         END;
  754.  
  755.     IF ORD4(possibleLoc + fInset.topLeft.vh[orthoVhs]) >= fSize.vh[orthoVhs] THEN
  756.         DoBreakFollowing := fSize.vh[orthoVhs]
  757.     ELSE
  758.         DoBreakFollowing := possibleLoc;
  759.     END;
  760.  
  761. {--------------------------------------------------------------------------------------------------}
  762. {$S TENonRes}
  763.  
  764. PROCEDURE TTEView.DoCalcViewPerPage(VAR viewPerPage: VPoint); OVERRIDE;
  765.  
  766.     VAR
  767.         vhs:                VHSelect;
  768.  
  769.     BEGIN
  770.     INHERITED DoCalcViewPerPage(viewPerPage);            { Get max amount allowed given margins }
  771.  
  772.     {$IFC qDebug}
  773.     IF gDebugPrinting THEN
  774.         BEGIN
  775.         WRITE('TTEView: incoming generic viewPerPage:');
  776.         WriteVPt(viewPerPage);
  777.         WRITELN;
  778.         END;
  779.     {$ENDC}
  780.  
  781.     IF (fStyleType <> kWithStyle) & (fHTE <> NIL) THEN    { Adjust for integral # of lines per page }
  782.         WITH fHTE^^ DO
  783.             viewPerPage.v := lineHeight * (viewPerPage.v DIV lineHeight);
  784.  
  785.     {$IFC qDebug}
  786.     IF gDebugPrinting THEN
  787.         BEGIN
  788.         WRITE('TTEView: computed viewPerPage:');
  789.         WriteVPt(viewPerPage);
  790.         WRITELN;
  791.         END;
  792.     {$ENDC}
  793.     END;
  794.  
  795. {--------------------------------------------------------------------------------------------------}
  796. {$S TERes}
  797.  
  798. FUNCTION TTEView.DoIdle(phase: IdlePhase): BOOLEAN; OVERRIDE;
  799.  
  800.     VAR
  801.         aRect:                Rect;
  802.  
  803.     BEGIN
  804.     DoIdle := FALSE;                                    { Didn't free myself }
  805.  
  806.     IF (fHTE <> NIL) & (fHTE^^.selEnd - fHTE^^.selStart = 0) & fViewEnabled THEN
  807.         BEGIN
  808.         IF Focus & IsVisible & fAcceptsChanges THEN
  809.             TEIdle(fHTE);
  810.         SetIdleFreq(MAX(GetCaretTime DIV 2, 1));        { Reset idle frequency in case user changed
  811.                                                          it}
  812.         END
  813.     ELSE
  814.         SetIdleFreq(kMaxIdleTime);                        { No need to bother anyone. }
  815.     END;
  816.  
  817. {--------------------------------------------------------------------------------------------------}
  818. {$S TERes}
  819.  
  820. FUNCTION TTEView.DoKeyCommand(ch: Char;
  821.                               aKeyCode: INTEGER;
  822.                               VAR info: EventInfo): TCommand; OVERRIDE;
  823. { The Tab character has no width in some fonts, and so can cause confusing screen feedback.
  824.  It is filtered out by default.  If you want to include it in your text union it into fControlChars. }
  825.  
  826.     VAR
  827.         aTypingCommand:     TTETypingCommand;
  828.         needNewCommand:     BOOLEAN;
  829.         handledCharacter:    BOOLEAN;
  830.  
  831.     BEGIN
  832.     DoKeyCommand := NIL;
  833.     handledCharacter := FALSE;
  834.  
  835.     IF IsViewEnabled THEN                                { if view is not enabled then we don't take
  836.                                                          ANY keystrokes }
  837.         BEGIN
  838.         IF (ch >= ' ') | (ch IN fControlChars) THEN     { Check that the character should be
  839.                                                          accepted }
  840.             BEGIN
  841.             IF (ch IN [chLeft, chRight, chUp, chDown]) & Focus THEN { check for pure movement keys }
  842.                 BEGIN
  843.                 DoneTyping;                             { Like mousedown, further typing = new cmd }
  844.                 fSpecsChanged := TRUE;
  845.                 TEKey(ch, fHTE);
  846.                 ScrollSelectionIntoView;
  847.                 handledCharacter := TRUE;
  848.                 END
  849.             ELSE IF fAcceptsChanges & Focus THEN
  850.                 BEGIN
  851.                 { Check max size for text, and that we're not running out of memory }
  852.                 IF (ch <> chBackspace) & (ch <> chFwdDelete) & (fHTE^^.selStart =
  853.                    fHTE^^.selEnd) THEN
  854.                     IF ((fMaxChars - GetHandleSize(fText)) < 1) | MemSpaceIsLow THEN
  855.                         BEGIN
  856.                         StdAlert(phTooManyChars);
  857.                         EXIT(DoKeyCommand);             { Flush further keystrokes }
  858.                         END;
  859.  
  860.                 { Pass the character to the typing command, creating a new one if necessary }
  861.  
  862.                 needNewCommand := (fTypingCommand = NIL);
  863.                 IF NOT needNewCommand THEN
  864.                     needNewCommand := fTypingCommand.fCompleted;
  865.  
  866.                 IF needNewCommand THEN
  867.                     BEGIN
  868.                     aTypingCommand := DoMakeTypingCommand(ch);
  869.                     fTypingCommand := aTypingCommand;
  870.                     DoKeyCommand := aTypingCommand;
  871.                     END
  872.                 ELSE
  873.                     BEGIN
  874.                     fTypingCommand.AddCharacter(ch);
  875.                     { Once you're typing (first character already processed) collecting subsequent
  876.                     characters really shouldn't affect the menus unless you're keeping a character
  877.                     count in them or something that depends on the aggregate of the characters you've
  878.                     typed.    The TextStyle for the first character would certainly apply to subsequent
  879.                     characters.  So, this is one ideal place to say that the event _DOES NOT_ affect
  880.                     the menus.    If the menus are already invalid they will stay so, but if they are
  881.                     valid then there is no need to invalidate them in the character collection process.
  882.                     When the user terminates the addition of characters with another event, the menus
  883.                     will be setup from that event.    If you really feel you must, then you can always
  884.                     override, call inherited and then set info.affectMenus back to true. (Rhymes with
  885.                     rue) }
  886.                     info.affectsMenus := FALSE;
  887.                     END;
  888.                 handledCharacter := TRUE;
  889.                 END
  890.  
  891.             END;
  892.         IF fIdleFreq = kMaxIdleTime THEN
  893.             SetIdleFreq(0);                             { Idle ASAP, since someone may somehow set
  894.                                                          an insertion point and want it to flash.
  895.                                                          (the idle time will be reset to match the
  896.                                                          caret time in doidle.)}
  897.         END;
  898.  
  899.     IF NOT handledCharacter THEN
  900.         DoKeyCommand := INHERITED DoKeyCommand(ch, aKeyCode, info);
  901.     END;
  902.  
  903. {--------------------------------------------------------------------------------------------------}
  904. {$S TESelCommand}
  905.  
  906. FUNCTION TTEView.DoMakeEditCommand(aCmdNumber: CmdNumber): TTECommand;
  907.  
  908.     VAR
  909.         aCutCopyCommand:    TTECutCopyCommand;
  910.         aPasteCommand:        TTEPasteCommand;
  911.         aClearCommand:        TTECommand;
  912.  
  913.     BEGIN
  914.     CASE aCmdNumber OF
  915.         cCut, cCopy:
  916.             BEGIN
  917.             New(aCutCopyCommand);
  918.             FailNIL(aCutCopyCommand);
  919.             aCutCopyCommand.ITECutCopyCommand(SELF, aCmdNumber);
  920.             DoMakeEditCommand := aCutCopyCommand;
  921.             END;
  922.  
  923.         cPaste:
  924.             BEGIN
  925.             New(aPasteCommand);
  926.             FailNIL(aPasteCommand);
  927.             aPasteCommand.ITEPasteCommand(SELF);
  928.             DoMakeEditCommand := aPasteCommand;
  929.             END;
  930.  
  931.         cClear:
  932.             BEGIN
  933.             New(aClearCommand);
  934.             FailNIL(aClearCommand);
  935.             aClearCommand.ITECommand(SELF, aCmdNumber, TRUE);
  936.             DoMakeEditCommand := aClearCommand;
  937.             END;
  938.  
  939.     END;
  940.     END;
  941.  
  942. {--------------------------------------------------------------------------------------------------}
  943. {$S TERes}
  944.  
  945. FUNCTION TTEView.DoMakeStyleCommand(aStyle: TextStyle;
  946.                                     itsCmdNumber: CmdNumber;
  947.                                     itsMode: INTEGER): TTEStyleCommand;
  948.  
  949.     VAR
  950.         aTEStyleCommand:    TTEStyleCommand;
  951.  
  952.     BEGIN
  953.     New(aTEStyleCommand);
  954.     FailNIL(aTEStyleCommand);
  955.     aTEStyleCommand.ITEStyleCommand(SELF, aStyle, itsCmdNumber, itsMode);
  956.     DoMakeStyleCommand := aTEStyleCommand;
  957.     END;
  958.  
  959. {--------------------------------------------------------------------------------------------------}
  960. {$S TERes}
  961.  
  962. FUNCTION TTEView.DoMakeTypingCommand(ch: Char): TTETypingCommand;
  963.  
  964.     VAR
  965.         aTypingCommand:     TTETypingCommand;
  966.  
  967.     BEGIN
  968.     New(aTypingCommand);
  969.     FailNIL(aTypingCommand);
  970.     aTypingCommand.ITETypingCommand(SELF, ch);
  971.     DoMakeTypingCommand := aTypingCommand;
  972.     END;
  973.  
  974. {--------------------------------------------------------------------------------------------------}
  975. {$S TESelCommand}
  976.  
  977. FUNCTION TTEView.DoMenuCommand(aCmdNumber: CmdNumber): TCommand; OVERRIDE;
  978.  
  979.     VAR
  980.         command:            TCommand;
  981.         aCutCopyCommand:    TTECutCopyCommand;
  982.         aPasteCommand:        TTEPasteCommand;
  983.         nChars:             LONGINT;
  984.         dataType:            ResType;
  985.  
  986.     BEGIN
  987.     DoMenuCommand := NIL;
  988.     CASE aCmdNumber OF
  989.         cCut, cCopy, cClear:
  990.             DoMenuCommand := DoMakeEditCommand(aCmdNumber);
  991.  
  992.         cPaste:
  993.             BEGIN
  994.             nChars := gApplication.GetDataToPaste(NIL, dataType);
  995.             IF nChars < 0 THEN
  996.             {$IFC qDebug}
  997.                 ProgramBreak('Couldn''t get data to paste') { ??? }
  998.                 {$ENDC}
  999.             ELSE
  1000.                 BEGIN
  1001.                 IF nChars - (fHTE^^.selEnd - fHTE^^.selStart) >
  1002.                    fMaxChars - GetHandleSize(fText) THEN
  1003.                     StdAlert(phTooManyChars)
  1004.                 ELSE
  1005.                     DoMenuCommand := DoMakeEditCommand(aCmdNumber);
  1006.                 END;
  1007.             END;
  1008.  
  1009.         cSelectAll:
  1010.             BEGIN
  1011.             IF Focus THEN
  1012.                 BEGIN
  1013.                 TESetSelect(0, fHTE^^.teLength, fHTE);
  1014.                 DoneTyping;
  1015.                 fSpecsChanged := TRUE;
  1016.                 ScrollSelectionIntoView;
  1017.                 END;
  1018.             END;
  1019.  
  1020.         OTHERWISE
  1021.             DoMenuCommand := INHERITED DoMenuCommand(aCmdNumber);
  1022.  
  1023.     END;
  1024.     END;
  1025.  
  1026. {--------------------------------------------------------------------------------------------------}
  1027. {$S TERes}
  1028.  
  1029. FUNCTION TTEView.DoMouseCommand(VAR theMouse: Point;
  1030.                                 VAR info: EventInfo;
  1031.                                 VAR hysteresis: Point): TCommand; OVERRIDE;
  1032.  
  1033.     BEGIN
  1034.     IF Focus & IsVisible THEN
  1035.         BEGIN
  1036.         pCurrTEView := SELF;                            { So the global clikLoop routine can forward
  1037.                                                          }
  1038.         DoneTyping;                                     { Mousedown terminates the Typing command }
  1039.         fSpecsChanged := TRUE;
  1040.         TEClick(theMouse, info.theShiftKey, fHTE);
  1041.  
  1042.         { …force a re-focus b/c the focusing in ClikLoop clips down to the destrect. }
  1043.         IF IsFocused THEN
  1044.             InvalidateFocus;
  1045.  
  1046.         IF fIdleFreq = kMaxIdleTime THEN
  1047.             SetIdleFreq(0);                             { Idle ASAP }
  1048.         END;
  1049.     DoMouseCommand := NIL;
  1050.     END;
  1051.  
  1052. {--------------------------------------------------------------------------------------------------}
  1053. {$S TENonRes}
  1054.  
  1055. PROCEDURE TTEView.DoneTyping;
  1056.  
  1057.     BEGIN
  1058.     IF fTypingCommand <> NIL THEN
  1059.         fTypingCommand.CompleteTyping;
  1060.     END;
  1061.  
  1062. {--------------------------------------------------------------------------------------------------}
  1063. {$S TERes}
  1064.  
  1065. FUNCTION TTEView.DoSetCursor(localPoint: Point;
  1066.                              cursorRgn: RgnHandle): BOOLEAN; OVERRIDE;
  1067.  
  1068.     VAR
  1069.         qdExtent:            Rect;
  1070.  
  1071.     BEGIN
  1072.     GetDefaultCursorRgn(localPoint,cursorRgn);
  1073.     UseROMMap(TRUE);
  1074.     SetCursor(GetCursor(iBeamCursor)^^);
  1075.     DoSetCursor := TRUE;
  1076.     END;
  1077.  
  1078. {--------------------------------------------------------------------------------------------------}
  1079. {$S TEPrint}
  1080.  
  1081. PROCEDURE TTEView.DoSetPageOffset(coord: VPoint); OVERRIDE;
  1082.  
  1083.     VAR
  1084.         vhs:                VHSelect;
  1085.  
  1086.     BEGIN
  1087.     INHERITED DoSetPageOffset(coord);
  1088.     FOR vhs := v TO h DO
  1089.         IF coord.vh[vhs] = 0 THEN
  1090.             gPageOffset.vh[vhs] := gPageOffset.vh[vhs] + fInset.topLeft.vh[vhs];
  1091.     END;
  1092.  
  1093. {--------------------------------------------------------------------------------------------------}
  1094. {$S TERes}
  1095.  
  1096. PROCEDURE TTEView.DoSetupMenus; OVERRIDE;
  1097.  
  1098.     VAR
  1099.         manyChars:            BOOLEAN;
  1100.  
  1101.     BEGIN
  1102.     INHERITED DoSetupMenus;
  1103.  
  1104.     WITH fHTE^^ DO
  1105.         manyChars := selStart < selEnd;
  1106.     IF NOT MemSpaceIsLow THEN
  1107.         BEGIN
  1108.         IF fAcceptsChanges THEN                         { One way or another, we can paste text }
  1109.             CanPaste('TEXT');                            { If styles exist, all the better }
  1110.  
  1111.         Enable(cCopy, manyChars);
  1112.         END;
  1113.     Enable(cSelectAll, (fHTE^^.teLength > 0));
  1114.  
  1115.  { We enable Cut even if space is low, since it's nice to be able to rescue some of
  1116.    the stuff you have to delete even if space is low.  Note that it is possible to
  1117.    get into the "can't do any commands" situation as a result.  You should be able
  1118.    to close and save the big document, then save the rescued text elsewhere, however. }
  1119.  
  1120.     Enable(cCut, manyChars & fAcceptsChanges);
  1121.     Enable(cClear, manyChars & fAcceptsChanges);
  1122.     END;
  1123.  
  1124. {--------------------------------------------------------------------------------------------------}
  1125. {$S TERes}
  1126.  
  1127. PROCEDURE TTEView.Draw(area: Rect); OVERRIDE;
  1128.  
  1129.     VAR
  1130.         hideSelection: BOOLEAN;
  1131.         
  1132.  
  1133.     BEGIN
  1134.     hideSelection := (gPrinting | gDrawingPictScrap) & BOOLEAN(fHTE^^.active);
  1135.     IF hideSelection THEN
  1136.         BEGIN                                        { …prevent selection from being drawn. }
  1137.         {$IFC qDebug}
  1138.         UseTempRgn('TTEView.Draw');
  1139.         {$ENDC}
  1140.         GetClip(gTempRgn);
  1141.         ClipRect(gZeroRect);
  1142.         TEDeactivate(fHTE);
  1143.         SetClip(gTempRgn);
  1144.         END;
  1145.  
  1146.  
  1147.     TEUpdate(area, fHTE);                { normal screen update handled by TextEdit directly }
  1148.  
  1149.     IF hideSelection THEN
  1150.         BEGIN
  1151.         GetClip(gTempRgn);
  1152.         ClipRect(gZeroRect);
  1153.         TEActivate(fHTE);
  1154.         SetClip(gTempRgn);
  1155.         {$IFC qDebug}
  1156.         DoneWithTempRgn;
  1157.         {$ENDC}
  1158.         END;
  1159.  
  1160.  
  1161.     INHERITED Draw(area);
  1162.     END;
  1163.  
  1164. {--------------------------------------------------------------------------------------------------}
  1165. {$S TENonRes}
  1166.  
  1167. PROCEDURE TTEView.ExtractStyles(VAR theStyles: TEStyleHandle;
  1168.                                 VAR theElements: STHandle);
  1169.  
  1170.     BEGIN
  1171.     theStyles := GetStylHandle(fHTE);
  1172.     theElements := theStyles^^.styleTab;
  1173.     END;
  1174.  
  1175. {--------------------------------------------------------------------------------------------------}
  1176. {$S TENonRes}
  1177.  
  1178. FUNCTION TTEView.ExtractText: Handle;
  1179.  
  1180.     BEGIN
  1181.     ExtractText := fText;
  1182.     END;
  1183.  
  1184. {--------------------------------------------------------------------------------------------------}
  1185. {$S TENonRes}
  1186.  
  1187. PROCEDURE TTEView.GetPrintExtent(VAR printExtent: VRect); OVERRIDE;
  1188.  
  1189.     BEGIN
  1190.     INHERITED GetPrintExtent(printExtent);
  1191.     WITH fInset DO
  1192.         BEGIN
  1193.         printExtent.top := printExtent.top + top;
  1194.         printExtent.left := printExtent.left + left;
  1195.         printExtent.bottom := printExtent.bottom - bottom;
  1196.         printExtent.right := printExtent.right - right;
  1197.         END;
  1198.     END;
  1199.  
  1200. {--------------------------------------------------------------------------------------------------}
  1201. {$S TEClipboard}
  1202.  
  1203. FUNCTION TTEView.GivePasteData(aDataHandle: Handle;
  1204.                                dataType: ResType): LONGINT; OVERRIDE;
  1205.  
  1206.     VAR
  1207.         oldStart:            INTEGER;
  1208.         oldEnd:             INTEGER;
  1209.         aSize:                LONGINT;
  1210.         aHandle:            Handle;
  1211.         err:                OSErr;
  1212.         savedPerm:            BOOLEAN;
  1213.         fi:                 FailInfo;
  1214.  
  1215. {--------------------------------------------------------------------------------------------------}
  1216.  
  1217.     PROCEDURE HdlGivePasteFailed(error: OSErr;
  1218.                                  message: LONGINT);
  1219.  
  1220.         BEGIN
  1221.         aHandle := DisposeIfHandle(aHandle);
  1222.         END;
  1223.  
  1224.     BEGIN
  1225.     savedPerm := FALSE;
  1226.     aSize := 0;                                         { Assume the worst }
  1227.     aHandle := NIL;
  1228.     CatchFailures(fi, HdlGivePasteFailed);
  1229.  
  1230.     IF dataType = 'TEXT' THEN
  1231.         BEGIN
  1232.         aSize := GetHandleSize(fText);
  1233.         IF aDataHandle <> NIL THEN
  1234.             BEGIN
  1235.             SetPermHandleSize(aDataHandle, aSize);        { Don't forget. This can fail }
  1236.             BlockMove(fText^, aDataHandle^, aSize);
  1237.             END;
  1238.         END
  1239.     ELSE IF dataType = 'styl' THEN
  1240.         BEGIN
  1241.         IF fStyleType = kWithStyle THEN
  1242.             IF NOT SpaceForStyles(0, MAXINT) THEN
  1243.                 Failure(noErr, 0)                        { We'll accept this error in worst case }
  1244.             ELSE
  1245.                 BEGIN
  1246.                 WITH fHTE^^ DO
  1247.                     BEGIN
  1248.                     oldStart := selStart;
  1249.                     oldEnd := selEnd;
  1250.                     END;
  1251.                 SetSelect(0, MAXINT, fHTE);
  1252.                 aHandle := Handle(GetStylScrap(fHTE));
  1253.                 SetSelect(oldStart, oldEnd, fHTE);
  1254.  
  1255.                 IF aHandle <> NIL THEN
  1256.                     BEGIN
  1257.                     aSize := GetHandleSize(aHandle);
  1258.                     IF aDataHandle <> NIL THEN
  1259.                         BEGIN
  1260.                         savedPerm := PermAllocation(TRUE);
  1261.                         LockHandleHigh(aHandle);        { Try to prevent fragmentation, in case
  1262.                                                          Can't move while we're copying it! }
  1263.  
  1264.                         err := PtrToXHand(aHandle^,     { Copy styles into user-supplied handle }
  1265.                                           aDataHandle, aSize);
  1266.                         HUnlock(aHandle);                { Okay for it to move again }
  1267.                         savedPerm := PermAllocation(savedPerm);
  1268.                         IF err <> noErr THEN            { Maybe enough for one copy, but not two! }
  1269.                             Failure(phStylesTooBig, phStylesTooBig + msgAlert);
  1270.                         END;
  1271.                     aHandle := DisposeIfHandle(aHandle);
  1272.                     END
  1273.                 ELSE IF aDataHandle <> NIL THEN         { Hmm. There _was_ enough memory, but the }
  1274.                     Failure(phStylesTooBig, phStylesTooBig + msgAlert); { …heap is probably pretty
  1275.                                                                          fragmented }
  1276.  
  1277.                 END;
  1278.         END
  1279.     ELSE
  1280.         Failure(noTypeErr, 0);
  1281.  
  1282.     FailSpaceIsLow;
  1283.     Success(fi);
  1284.     GivePasteData := aSize;
  1285.     END;
  1286.  
  1287. {--------------------------------------------------------------------------------------------------}
  1288. {$S TENonRes}
  1289.  
  1290. PROCEDURE TTEView.InstallSelection(wasActive, beActive: BOOLEAN); OVERRIDE;
  1291.  
  1292.     VAR
  1293.         aDiscard:            INTEGER;
  1294.  
  1295.     BEGIN
  1296.     IF fHTE <> NIL THEN                                 { fHTE is set to NIL by TTEView.Free …since
  1297.                                                          InstallSelection is then …called by
  1298.                                                          INHERITED Free. }
  1299.         BEGIN
  1300.         IF beActive THEN
  1301.             BEGIN
  1302.             IF fIdleFreq = kMaxIdleTime THEN
  1303.                 SetIdleFreq(0);                         { Idle ASAP }
  1304.             IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN
  1305.                 aDiscard := SetKeyScript(Font2Script(fTextStyle.tsFont));
  1306.             IF Focus THEN                                { Try to focus because TEActivate may draw }
  1307.                 TEActivate(fHTE);
  1308.             pCurrTEView := SELF;                        { So the global clikLoop routine can forward
  1309.                                                          }
  1310.             END
  1311.         ELSE
  1312.             BEGIN
  1313.             IF Focus THEN                                { Try to focus because TEDeactivate may draw
  1314.                                                          }
  1315.                 TEDeactivate(fHTE);
  1316.             DoneTyping;
  1317.             fSpecsChanged := TRUE;
  1318.             END;
  1319.         END;
  1320.     END;
  1321.  
  1322. {--------------------------------------------------------------------------------------------------}
  1323. {$S TEOpen}
  1324.  
  1325. PROCEDURE TTEView.MakeTERecord;
  1326.  
  1327.     VAR
  1328.         anHTE:                TEHandle;
  1329.         dest:                Rect;
  1330.         oldPort:            GrafPtr;
  1331.         fi:                 FailInfo;
  1332.         aTextStyle:         TextStyle;
  1333.  
  1334.     PROCEDURE HdlMakeFailed(error: OSErr;
  1335.                             message: LONGINT);
  1336.  
  1337.         BEGIN
  1338.         Free;
  1339.         END;
  1340.  
  1341.     BEGIN
  1342.     GetPort(oldPort);
  1343.     SetPort(gWorkPort);
  1344.     aTextStyle := fTextStyle;
  1345.     SetPortTextStyle(aTextStyle);
  1346.  
  1347.     dest.topLeft := fInset.topLeft;
  1348.     dest.right := fSize.h - fInset.right;
  1349.     dest.bottom := fSize.v - fInset.bottom;
  1350.  
  1351.     IF fStyleType = kWithStyle THEN
  1352.         anHTE := TEStylNew(dest, dest)                    { Open a styled record if requested }
  1353.     ELSE
  1354.         anHTE := TENew(dest, dest);                     { …otherwise, do it the old way }
  1355.  
  1356.     SetPort(oldPort);
  1357.  
  1358.     CatchFailures(fi, HdlMakeFailed);                    { In case we couldn't create the TEHandle. }
  1359.     FailNIL(anHTE);                                     { Make sure we actually created one }
  1360.     fHTE := anHTE;                                        { We did, so save off TE handle }
  1361.     gDefClikLoopProc := anHTE^^.ClikLoop;                { Just in case we want to restore it… }
  1362.     { Note that the system call SetClikLoop }
  1363.     { _cannot_ be used to set the clikProc of }
  1364.     { the TERecord. This is because the default }
  1365.     { clikproc does not follow the Pascal Parameter }
  1366.     { passing conventions that this procedure expects. }
  1367.  
  1368.     SetJustification(fJustification, kDontRedraw);        { Set justification to requested value }
  1369.     ChangeWrap(fAutoWrap, FALSE);                        { Install auto wrap (or CR only) }
  1370.     FailNoReserve;                                        { Got to have some reserve tank }
  1371.     Success(fi);
  1372.  
  1373.     BeInPort(GetGrafPort);                                { Associate with real port }
  1374.     END;
  1375.  
  1376. {--------------------------------------------------------------------------------------------------}
  1377. {$S TERes}
  1378.  
  1379. PROCEDURE TTEView.RecalcText;
  1380.  
  1381.     BEGIN
  1382.     TECalText(fHTE);
  1383.     END;
  1384.  
  1385. {--------------------------------------------------------------------------------------------------}
  1386. {$S TENonRes}
  1387.  
  1388. PROCEDURE TTEView.Resize(width, height: VCoordinate;
  1389.                          invalidate: BOOLEAN); OVERRIDE;
  1390.  
  1391.     VAR
  1392.         needCalText:        BOOLEAN;
  1393.         r:                    Rect;
  1394.         oldSize:            VPoint;
  1395.         actualJust:            INTEGER;
  1396.  
  1397.     BEGIN
  1398.     oldSize := fSize;
  1399.     INHERITED Resize(width, height, invalidate);
  1400.     IF fHTE <> NIL THEN
  1401.         BEGIN
  1402.         r.topLeft := fInset.topLeft;
  1403.         r.right := fSize.h - fInset.right;
  1404.         r.bottom := fSize.v - fInset.bottom;
  1405.  
  1406.         needCalText := (r.right <> fHTE^^.destRect.right);
  1407.         StuffTERects(r);
  1408.         IF needCalText THEN
  1409.             BEGIN
  1410.             RecalcText;
  1411.             SynchView(kDontRedraw);
  1412.             actualJust := GetActualJustification(fJustification);
  1413.             IF invalidate & ((fAutoWrap & (fSize.h <> oldSize.h) & (fSize.v <> oldSize.v))
  1414.             { All bets are off }
  1415.             | ((actualJust = teJustRight) | (actualJust = teJustCenter))) THEN
  1416.                 ForceRedraw;
  1417.             END;
  1418.         END;
  1419.     END;
  1420.  
  1421. {--------------------------------------------------------------------------------------------------}
  1422. {$S TERes}
  1423.  
  1424. PROCEDURE TTEView.ScrollSelectionIntoView;
  1425.  
  1426.     VAR
  1427.         vhs:                VHSelect;
  1428.         newLoc:             Point;
  1429.         newSelLoc:            Point;
  1430.         selectionRect:        Rect;
  1431.         minToSee:            Point;
  1432.         visRect:            Rect;
  1433.         vSelectionRect:     VRect;
  1434.  
  1435.     BEGIN
  1436.     { ??? should we have an option to walk the superviews, scrolling as many scrollers as necessary
  1437.     to reveal the selection? }
  1438.     IF (GetScroller(FALSE) <> NIL) & Focus THEN         { Can't scroll selection if we don't have }
  1439.         BEGIN                                            { … a scroller! }
  1440.         IF fIdleFreq = kMaxIdleTime THEN
  1441.             SetIdleFreq(0);                             { Idle ASAP }
  1442.         GetVisibleRect(visRect);
  1443.         CalcSelLoc(selectionRect);
  1444.  
  1445.         {$IFC qDebug}
  1446.         IF gIntenseDebugging THEN
  1447.             BEGIN
  1448.             WRITE('Visible Rect was: '); WriteRect(visRect);
  1449.             WRITE('; Sel Rect was: '); WriteRect(selectionRect); WRITELN;
  1450.             END;
  1451.         {$ENDC}
  1452.  
  1453.         IF NOT RectsNest(visRect, selectionRect) THEN
  1454.             BEGIN
  1455.             { Scroll the selection into view.  accounting for the user's preference for how much to
  1456.             jump at a time with fMinAhead. }
  1457.             SetPt(minToSee, Min(fMinAhead, fSize.h - selectionRect.left), LengthRect(selectionRect,
  1458.                   v));
  1459.             {$IFC qDebug}
  1460.             IF gIntenseDebugging THEN
  1461.                 BEGIN
  1462.                 WrLblRect('RevealRect: r', selectionRect);
  1463.                 WrLblPt(', minToSee', minToSee);
  1464.                 WRITELN;
  1465.                 END;
  1466.             {$ENDC}
  1467.             QDToViewRect(selectionRect, vSelectionRect);
  1468.             RevealRect(vSelectionRect, minToSee, kRedraw);
  1469.             IF Focus THEN;                                { Refocus in newly-scrolled position. Why???
  1470.                                                          does our caller have a dependency on this?
  1471.                                                          }
  1472.             END;
  1473.         END
  1474.     ELSE IF qNeedsROM128K | gConfiguration.hasROM128K THEN
  1475.         IF NOT fAutoWrap & (fHTE <> NIL) THEN
  1476.             TESelView(fHTE);
  1477.     END;
  1478.  
  1479. {--------------------------------------------------------------------------------------------------}
  1480. {$S TENonRes}
  1481.  
  1482. PROCEDURE TTEView.SetJustification(newJust: INTEGER;
  1483.                                    redraw: BOOLEAN);
  1484.  
  1485.     BEGIN
  1486.     TESetJust(newJust, fHTE);
  1487.     fJustification := newJust;
  1488.     IF redraw THEN
  1489.         ForceRedraw;
  1490.     END;
  1491.  
  1492. {--------------------------------------------------------------------------------------------------}
  1493. {$S TENonRes}
  1494.  
  1495. PROCEDURE TTEView.SetOneStyle(theStart, theEnd, theMode: INTEGER;
  1496.                               theStyle: TextStyle;
  1497.                               redraw: BOOLEAN);
  1498.  
  1499.     VAR
  1500.         saveStart:            INTEGER;
  1501.         saveEnd:            INTEGER;
  1502.         fInfo:                FontInfo;
  1503.         newStyle:            TextStyle;
  1504.  
  1505.     BEGIN
  1506.     InvalidateFocus;                                    { ??? THIS SHOULDN'T BE NECESSARY! ??? }
  1507.     IF Focus THEN;
  1508.     IF fStyleType = kWithStyle THEN
  1509.         BEGIN
  1510.         WITH fHTE^^ DO
  1511.             BEGIN
  1512.             saveStart := selStart;
  1513.             saveEnd := selEnd;
  1514.             END;
  1515.         SetSelect(theStart, theEnd, fHTE);
  1516.         TESetStyle(theMode, theStyle, redraw, fHTE);
  1517.         SetSelect(saveStart, saveEnd, fHTE);
  1518.         END
  1519.     ELSE
  1520.         BEGIN
  1521.         IF theMode = doAll THEN
  1522.             newStyle := theStyle
  1523.         ELSE
  1524.             BEGIN
  1525.             newStyle := fTextStyle;
  1526.             IF BAND(theMode, doFont) <> 0 THEN
  1527.                 BEGIN
  1528.                 newStyle.tsFont := theStyle.tsFont;
  1529.  
  1530.                 IF qNeedsScriptManager | gConfiguration.hasScriptManager THEN { …if Script Mgr is
  1531.                        installed, change }
  1532.                     KeyScript(Font2Script(newStyle.tsFont)); { …keybd input system to match new font
  1533.                                                               }
  1534.                 END;
  1535.             IF BAND(theMode, doFace) <> 0 THEN
  1536.                 newStyle.tsFace := theStyle.tsFace;
  1537.             IF BAND(theMode, doColor) <> 0 THEN
  1538.                 newStyle.tsColor := theStyle.tsColor;
  1539.             IF BAND(theMode, addSize) <> 0 THEN
  1540.                 newStyle.tsSize := newStyle.tsSize + theStyle.tsSize
  1541.             ELSE IF BAND(theMode, doSize) <> 0 THEN
  1542.                 newStyle.tsSize := theStyle.tsSize;
  1543.             END;
  1544.  
  1545.         GetTextStyleFontInfo(newStyle, fInfo);            { Need to get font's height and ascent. }
  1546.  
  1547.         WITH fHTE^^, newStyle, fInfo DO
  1548.             BEGIN
  1549.             txSize := tsSize;
  1550.             txFont := tsFont;
  1551.             txFace := tsFace;
  1552.             fontAscent := ascent;
  1553.             lineHeight := ascent + descent + leading;
  1554.             SetIfColor(tsColor);
  1555.             END;
  1556.         fTextStyle := newStyle;
  1557.         END;
  1558.  
  1559.     IF TRUE                                             { (fStyleType = kWithoutStyle) | (theStart
  1560.                                                          <> theEnd) } THEN
  1561.         BEGIN
  1562.         RecalcText;
  1563.         SynchView(redraw & (fStyleType = kWithStyle));
  1564.         IF redraw & (fStyleType = kWithoutStyle) THEN
  1565.             ForceRedraw;
  1566.         END;
  1567.     fSpecsChanged := TRUE;
  1568.     END;
  1569.  
  1570. {--------------------------------------------------------------------------------------------------}
  1571. {$S TENonRes}
  1572.  
  1573. PROCEDURE TTEView.SetText(theText: Str255);
  1574.  
  1575.     VAR
  1576.         theTextHandle:        Handle;
  1577.  
  1578.     BEGIN
  1579.     IF fHTE <> NIL THEN                                 { If we're replacing text, styles are kaput
  1580.                                                          }
  1581.         BEGIN
  1582.         FailOSErr(PtrToHand(@theText[1], theTextHandle, LENGTH(theText)));
  1583.         StuffText(theTextHandle);
  1584.         END;
  1585.     END;
  1586.  
  1587. {--------------------------------------------------------------------------------------------------}
  1588. {$S TENonRes}
  1589.  
  1590. PROCEDURE TTEView.ShowReverted; OVERRIDE;
  1591.  
  1592.     BEGIN
  1593.     RecalcText;
  1594.     fLastHeight := 0;
  1595.     fLastWidth := 0;
  1596.     INHERITED ShowReverted;
  1597.     END;
  1598.  
  1599. {--------------------------------------------------------------------------------------------------}
  1600. {$S TENonRes}
  1601.  
  1602. FUNCTION TTEView.SpaceForStyles(rangeStart, rangeEnd: LONGINT): BOOLEAN;
  1603.  
  1604.     VAR
  1605.         h:                    Handle;
  1606.  
  1607.     BEGIN
  1608.     h := NewPermHandle(TENumStyles(rangeStart, rangeEnd, fHTE) * SIZEOF(ScrpSTElement) + 2);
  1609.     IF (h = NIL) THEN
  1610.         BEGIN
  1611.         StdAlert(phStylesTooBig);
  1612.         SpaceForStyles := FALSE;
  1613.         END
  1614.     ELSE
  1615.         BEGIN
  1616.         h := DisposeIfHandle(h);                        { Release memory back to the system }
  1617.         SpaceForStyles := TRUE;
  1618.         END;
  1619.     END;
  1620.  
  1621. {--------------------------------------------------------------------------------------------------}
  1622. {$S TENonRes}
  1623.  
  1624. PROCEDURE TTEView.StuffStyles(theStyles: TEStyleHandle;
  1625.                               theElements: STHandle);
  1626.  
  1627.     VAR
  1628.         oldStyles:            TEStyleHandle;
  1629.         oldElements:        STHandle;
  1630.         oldLineHeights:     LHHandle;
  1631.         theNullStyles:        nullSTHandle;
  1632.         theScrpHandle:        STScrpHandle;
  1633.         err:                OSErr;
  1634.  
  1635.     BEGIN
  1636.     IF (fStyleType = kWithStyle) & (fHTE <> NIL) THEN
  1637.         BEGIN
  1638.         oldStyles := GetStylHandle(fHTE);
  1639.  
  1640.         WITH oldStyles^^ DO
  1641.             BEGIN
  1642.             oldElements := styleTab;
  1643.             oldLineHeights := lhTab;
  1644.             theNullStyles := nullStyle;
  1645.             theScrpHandle := nullStyle^^.nullScrap;
  1646.             END;
  1647.  
  1648.         DisposIfHandle(oldElements);
  1649.  
  1650.         WITH theStyles^^ DO
  1651.             BEGIN
  1652.             styleTab := theElements;                    { Replace STElements handle }
  1653.             lhTab := oldLineHeights;                    { Replace line heights table handle }
  1654.             nullStyle := theNullStyles;                 { Replace null style handle }
  1655.             nullStyle^^.nullScrap := theScrpHandle;
  1656.             teRefCon := LONGINT(SELF);                    { store ourselves as the refcon reference }
  1657.             END;
  1658.  
  1659.         { NOTE!! SetStylHandle will dispose of oldStyles for us! }
  1660.         SetStylHandle(theStyles, fHTE);
  1661.  
  1662.         RecalcText;
  1663.         END;
  1664.     END;
  1665.  
  1666. {--------------------------------------------------------------------------------------------------}
  1667. {$S TENonRes}
  1668.  
  1669. PROCEDURE TTEView.StuffText(theText: Handle);
  1670.  
  1671.     VAR
  1672.         styles:             TEStyleHandle;
  1673.         textLength:         LONGINT;
  1674.  
  1675.     BEGIN
  1676.     IF fHTE <> NIL THEN                                 { If we're replacing text, styles are kaput
  1677.                                                          }
  1678.         BEGIN
  1679.         textLength := GetHandleSize(theText);            { Check size of new text }
  1680.         IF textLength > fMaxChars THEN
  1681.             BEGIN
  1682.             {$IFC qDebug}
  1683.             ProgramBreak('Text size exceeds maximum for this view');
  1684.             {$ENDC}
  1685.             Failure(minErr, 0);                         { ??? Assign a message }
  1686.             END;
  1687.  
  1688.         IF fSavedTEHandle <> theText THEN
  1689.             BEGIN
  1690.             fSavedTEHandle := DisposeIfHandle(fSavedTEHandle); { …we have no choice but to dispose
  1691.                                                                 it }
  1692.             fSavedTEHandle := fHTE^^.hText;             { Save existing handle }
  1693.             END;
  1694.         WITH fHTE^^ DO
  1695.             BEGIN
  1696.             hText := theText;                            { Install new handle }
  1697.             fText := theText;                            { Make a local copy, too }
  1698.             teLength := textLength;                     { Tell TE how long we are }
  1699.             END;
  1700.  
  1701.         IF fStyleType = kWithStyle THEN                 { Fix for styled TE. Yuk. }
  1702.             BEGIN
  1703.             styles := GetStylHandle(fHTE);
  1704.             styles^^.runs[1].startChar := SUCC(fHTE^^.teLength);
  1705.             styles^^.nRuns := 1;
  1706.             styles^^.nStyles := 1;
  1707.             { Thanks to map }
  1708.             END;
  1709.         END;
  1710.     END;
  1711.  
  1712. {--------------------------------------------------------------------------------------------------}
  1713. {$S TENonRes}
  1714.  
  1715. PROCEDURE TTEView.StuffTERects(newTERect: Rect);
  1716.  
  1717.     VAR
  1718.         aFontInfo:            FontInfo;
  1719.  
  1720.     BEGIN
  1721.  
  1722.     GetFontInfo(aFontInfo);
  1723.     WITH newTERect DO
  1724.         right := MAX(right, left + aFontInfo.widMax);
  1725.     WITH fHTE^^ DO
  1726.         BEGIN
  1727.         destRect := newTERect;
  1728.         viewRect := newTERect;
  1729.         END;
  1730.     END;
  1731.  
  1732. {--------------------------------------------------------------------------------------------------}
  1733. {$S TERes}
  1734.  
  1735. PROCEDURE TTEView.SynchView(redraw: BOOLEAN);
  1736.     CONST
  1737.         kInsertionBarWidth = 1;                        { We all _KNOW_ an insertion bar is one
  1738.                                                     pixel wide right? }
  1739.  
  1740.     VAR
  1741.         aRect:                Rect;
  1742.         theHeight:            LONGINT;
  1743.         theWidth:            LONGINT;
  1744.         doRealWidth:        BOOLEAN;
  1745.  
  1746.     BEGIN
  1747.     theHeight := CalcRealHeight;
  1748.  
  1749.     doRealWidth := (fSizeDeterminer[h] = sizeVariable) & NOT fStyleType & NOT fAutoWrap;
  1750.     IF doRealWidth THEN
  1751.         theWidth := CalcRealWidth + kInsertionBarWidth * 2;
  1752.  
  1753.     IF (fLastHeight <> theHeight) | (doRealWidth & (fLastWidth <> theWidth)) THEN
  1754.         BEGIN
  1755.         IF doRealWidth THEN
  1756.             fLastWidth := theWidth; { Width is expensive to calculate.  Cache for CalcMinSize }
  1757.  
  1758.         AdjustSize;                                     { may need to grow view }
  1759.         fLastHeight := theHeight;                        { Remember new height value }
  1760.         END;
  1761.  
  1762.     IF redraw & Focus THEN
  1763.   { First, make sure selection is visible (this conveniently focuses). Then,
  1764.    repair any extra feedback which TextEdit may have mashed. }
  1765.         BEGIN
  1766.         ScrollSelectionIntoView;
  1767.         DoHighlightSelection(hlOff, fHLDesired);
  1768.         IF fPrintHandler <> NIL THEN
  1769.             BEGIN
  1770.             GetVisibleRect(aRect);
  1771.             DoDrawPrintFeedback(aRect);
  1772.             END;
  1773.         END;
  1774.     END;
  1775.  
  1776. {--------------------------------------------------------------------------------------------------}
  1777. {$S TENonRes}
  1778.  
  1779. PROCEDURE TTEView.WriteToDeskScrap; OVERRIDE;
  1780.  
  1781.     VAR
  1782.         aHandle:            Handle;
  1783.  
  1784.     BEGIN
  1785.     FailOSErr(PutDeskScrapData('TEXT', fText));
  1786.  
  1787.     IF (fStyleType = kWithStyle) & SpaceForStyles(0, MAXINT) THEN
  1788.         BEGIN
  1789.         SetSelect(0, MAXINT, fHTE);
  1790.         aHandle := Handle(GetStylScrap(fHTE));
  1791.         FailNIL(aHandle);
  1792.         FailOSErr(PutDeskScrapData('styl', aHandle));
  1793.         END;
  1794.     END;
  1795.  
  1796. {--------------------------------------------------------------------------------------------------}
  1797. {$S TERes}
  1798.  
  1799. PROCEDURE TTEView.ViewEnable(state, redraw: BOOLEAN);
  1800.  
  1801.     BEGIN
  1802.     IF state & (fIdleFreq = kMaxIdleTime) THEN
  1803.         SetIdleFreq(0);                                 { Get correct idle set ASAP }
  1804.  
  1805.     INHERITED ViewEnable(state, redraw);
  1806.     END;
  1807.  
  1808. {--------------------------------------------------------------------------------------------------}
  1809. {$S TEDebug}
  1810.  
  1811. PROCEDURE TTEView.IdentifySoftware; OVERRIDE;
  1812.  
  1813.     BEGIN
  1814.     WRITELN('UTEView of 14 Feb 90 (Valentine''s Day), Compiled on ', COMPDATE, ' @ ', COMPTIME);
  1815.     INHERITED IdentifySoftware;
  1816.     END;
  1817.  
  1818. {--------------------------------------------------------------------------------------------------}
  1819. {$S TEFields}
  1820.  
  1821. PROCEDURE TTEView.Fields(PROCEDURE DoToField(fieldName: Str255;
  1822.                                              fieldAddr: Ptr;
  1823.                                              fieldType: INTEGER)); OVERRIDE;
  1824.  
  1825.     BEGIN
  1826.     DoToField('TTEView', NIL, bClass);
  1827.     DoToField('fHTE', @fHTE, bTEHandle);
  1828.     DoToField('fText', @fText, bHandle);
  1829.     DoToField('fSavedTEHandle', @fSavedTEHandle, bHandle);
  1830.     DoToField('fInset', @fInset, bRect);
  1831.     DoToField('fKeyCmdNumber', @fKeyCmdNumber, bCmdNumber);
  1832.     DoToField('fMaxChars', @fMaxChars, bInteger);
  1833.     DoToField('fLastHeight', @fLastHeight, bLongInt);
  1834.     DoToField('fLastWidth', @fLastWidth, bLongInt);
  1835.     DoToField('fTypingCommand', @fTypingCommand, bObject);
  1836.     {$Push} {$H-}
  1837.     TextStyleFields('fTextStyle', fTextStyle, DoToField);
  1838.     {$Pop}
  1839.     DoToField('fJustification', @fJustification, bInteger);
  1840.     DoToField('fAcceptsChanges', @fAcceptsChanges, bBoolean);
  1841.     DoToField('fStyleType', @fStyleType, bBoolean);
  1842.     DoToField('fAutoWrap', @fAutoWrap, bBoolean);
  1843.     DoToField('fFreeText', @fFreeText, bBoolean);
  1844.     DoToField('fSpecsChanged', @fSpecsChanged, bBoolean);
  1845.     DoToField('fLastLine', @fLastLine, bInteger);
  1846.     DoToField('fLastPageBreak', @fLastPageBreak, bInteger);
  1847.     DoToField('fControlChars', @fControlChars, bHexLongInt);
  1848.     DoToField('fMinAhead', @fMinAhead, bInteger);
  1849.  
  1850.     INHERITED Fields(DoToField);
  1851.     END;
  1852.